﻿// owner 蒋家伟
#include "SerialPort.h"

// qt
#include <QThread>
#include <QString>

// jsdk
#include "Dbg_Warn_Define.h"

using namespace jsdk;

jsdk::SerialPort::SerialPort()
{
}

OwnerPtr<SerialPort> jsdk::SerialPort::create(ISerialPortEventHandler * pSerialPortEventHandler)
{
    OwnerPtr<SerialPort> opSerialPort = NEW_AS_OWNERPTR(SerialPort);

    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSerialPort, L"串口对象创建失败", L"蒋家伟", L"2023-07-26");
    opSerialPort->m_opSerialPortWorker.swap(SerialPortWorker::create(pSerialPortEventHandler));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSerialPort->m_opSerialPortWorker, L"串口工作对象创建失败", L"蒋家伟", L"2023-07-26");

    opSerialPort->m_opThread.swap(NEW_AS_OWNERPTR_WITH_DELETER(QThread, ThreadDeleter));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSerialPort->m_opThread, L"串口工作线程创建失败", L"蒋家伟", L"2023-07-26");

    return std::move(opSerialPort);
}

bool jsdk::SerialPort::init() const
{
    // 跨线程信号与槽连接
    bool success = connect(
        this, 
        SIGNAL(connectSerialPort(
            QString,
            int,
            short,
            short,
            short,
            short)),
        m_opSerialPortWorker.get(),
        SLOT(onConnect(
            QString ,
            int,
            short,
            short,
            short,
            short)
            )
        );
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(success, L"串口连接信号与槽创建失败", L"蒋家伟", L"2023-07-26");

    success = connect(this, SIGNAL(sendMessage(QByteArray, qint64)), m_opSerialPortWorker.get(), SLOT(onSend(QByteArray, qint64)));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(success, L"串口发送信号与槽创建失败", L"蒋家伟", L"2023-07-26");

    return success;
}

void jsdk::SerialPort::connected(
    const std::string& portName,
    const int baudRate,
    const short dataBits,
    const short stopBits,
    const short parity,
    const short flowControl)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_opSerialPortWorker && !m_opSerialPortWorker->isOnLine(), L"当前串口工作对象没有创建成功或者正在工作", L"蒋家伟", L"2023-07-26");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_opThread, L"线程对象创建失败", L"蒋家伟", L"2023-07-26");

    bool success = init();
    DBG_WARN_AND_RETURN_VOID_UNLESS(success, L"套接字对象信号与槽连接失败", L"蒋家伟", L"2023-07-26");

    m_opSerialPortWorker->moveToThread(m_opThread.get());
    m_opThread->start();

    // 发给Worker
    emit connectSerialPort(
        QString::fromStdString(portName), 
        baudRate, 
        dataBits, 
        stopBits, 
        parity, 
        flowControl
        );
}

void jsdk::SerialPort::send(std::string&& msg, qint64 length) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_opSerialPortWorker && m_opSerialPortWorker->isOnLine(), L"当前串口工作对象没有创建成功或者没有在工作", L"蒋家伟", L"2023-07-26");
    // 发给Worker
    emit sendMessage(QByteArray(msg.c_str(), length), length);
}

void jsdk::SerialPort::reconnect(
    const std::string& portName,
    const int baudRate,
    const short dataBits,
    const short stopBits,
    const short parity,
    const short flowControl
    ) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_opSerialPortWorker && !m_opSerialPortWorker->isOnLine(), L"当前串口工作对象没有创建成功或者正在工作", L"蒋家伟", L"2023-07-26");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_opThread, L"线程对象创建失败", L"蒋家伟", L"2023-07-26");

    // 发给Worker
    emit connectSerialPort(
        QString::fromStdString(portName),
        static_cast<QSerialPort::BaudRate>(baudRate),
        static_cast<QSerialPort::DataBits>(dataBits),
        static_cast<QSerialPort::StopBits>(stopBits),
        static_cast<QSerialPort::Parity>(parity),
        static_cast<QSerialPort::FlowControl>(flowControl)
        );
}

bool jsdk::SerialPort::isOnLine() const
{
    return m_opSerialPortWorker && m_opSerialPortWorker->isOnLine();
}